From 7bb5b8df0bc8fc0d5b7958ec522d9a9b5b441e18 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 3 Sep 2017 09:54:47 -0400 Subject: [PATCH] A somewhat working blur shader This is a very direct implementation of a Gaussian blur, without any optimizations. --- gsk/gskvulkanblurpipeline.c | 129 ++++++++++++++++++ gsk/gskvulkanblurpipelineprivate.h | 32 +++++ gsk/gskvulkanrender.c | 4 + gsk/gskvulkanrenderpass.c | 78 +++++++++++ gsk/gskvulkanrenderprivate.h | 3 + gsk/meson.build | 1 + .../vulkan/blur-clip-rounded.frag.spv | Bin 0 -> 10812 bytes .../vulkan/blur-clip-rounded.vert.spv | Bin 0 -> 5172 bytes gsk/resources/vulkan/blur-clip.frag.spv | Bin 0 -> 4068 bytes gsk/resources/vulkan/blur-clip.vert.spv | Bin 0 -> 5172 bytes gsk/resources/vulkan/blur.frag | 50 +++++++ gsk/resources/vulkan/blur.frag.glsl | 13 ++ gsk/resources/vulkan/blur.frag.spv | Bin 0 -> 4068 bytes gsk/resources/vulkan/blur.vert | 41 ++++++ gsk/resources/vulkan/blur.vert.glsl | 30 ++++ gsk/resources/vulkan/blur.vert.spv | Bin 0 -> 3440 bytes gsk/resources/vulkan/meson.build | 2 + 17 files changed, 383 insertions(+) create mode 100644 gsk/gskvulkanblurpipeline.c create mode 100644 gsk/gskvulkanblurpipelineprivate.h create mode 100644 gsk/resources/vulkan/blur-clip-rounded.frag.spv create mode 100644 gsk/resources/vulkan/blur-clip-rounded.vert.spv create mode 100644 gsk/resources/vulkan/blur-clip.frag.spv create mode 100644 gsk/resources/vulkan/blur-clip.vert.spv create mode 100644 gsk/resources/vulkan/blur.frag create mode 100644 gsk/resources/vulkan/blur.frag.glsl create mode 100644 gsk/resources/vulkan/blur.frag.spv create mode 100644 gsk/resources/vulkan/blur.vert create mode 100644 gsk/resources/vulkan/blur.vert.glsl create mode 100644 gsk/resources/vulkan/blur.vert.spv diff --git a/gsk/gskvulkanblurpipeline.c b/gsk/gskvulkanblurpipeline.c new file mode 100644 index 0000000000..779bf81ec0 --- /dev/null +++ b/gsk/gskvulkanblurpipeline.c @@ -0,0 +1,129 @@ +#include "config.h" + +#include "gskvulkanblurpipelineprivate.h" + +struct _GskVulkanBlurPipeline +{ + GObject parent_instance; +}; + +typedef struct _GskVulkanBlurInstance GskVulkanBlurInstance; + +struct _GskVulkanBlurInstance +{ + float rect[4]; + float tex_rect[4]; + float blur_radius; +}; + +G_DEFINE_TYPE (GskVulkanBlurPipeline, gsk_vulkan_blur_pipeline, GSK_TYPE_VULKAN_PIPELINE) + +static const VkPipelineVertexInputStateCreateInfo * +gsk_vulkan_blur_pipeline_get_input_state_create_info (GskVulkanPipeline *self) +{ + static const VkVertexInputBindingDescription vertexBindingDescriptions[] = { + { + .binding = 0, + .stride = sizeof (GskVulkanBlurInstance), + .inputRate = VK_VERTEX_INPUT_RATE_INSTANCE + } + }; + static const VkVertexInputAttributeDescription vertexInputAttributeDescription[] = { + { + .location = 0, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = 0, + }, + { + .location = 1, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanBlurInstance, tex_rect), + }, + { + .location = 2, + .binding = 0, + .format = VK_FORMAT_R32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanBlurInstance, blur_radius), + } + }; + static const VkPipelineVertexInputStateCreateInfo info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + .vertexBindingDescriptionCount = G_N_ELEMENTS (vertexBindingDescriptions), + .pVertexBindingDescriptions = vertexBindingDescriptions, + .vertexAttributeDescriptionCount = G_N_ELEMENTS (vertexInputAttributeDescription), + .pVertexAttributeDescriptions = vertexInputAttributeDescription + }; + + return &info; +} + +static void +gsk_vulkan_blur_pipeline_finalize (GObject *gobject) +{ + //GskVulkanBlurPipeline *self = GSK_VULKAN_BLUR_PIPELINE (gobject); + + G_OBJECT_CLASS (gsk_vulkan_blur_pipeline_parent_class)->finalize (gobject); +} + +static void +gsk_vulkan_blur_pipeline_class_init (GskVulkanBlurPipelineClass *klass) +{ + GskVulkanPipelineClass *pipeline_class = GSK_VULKAN_PIPELINE_CLASS (klass); + + G_OBJECT_CLASS (klass)->finalize = gsk_vulkan_blur_pipeline_finalize; + + pipeline_class->get_input_state_create_info = gsk_vulkan_blur_pipeline_get_input_state_create_info; +} + +static void +gsk_vulkan_blur_pipeline_init (GskVulkanBlurPipeline *self) +{ +} + +GskVulkanPipeline * +gsk_vulkan_blur_pipeline_new (GskVulkanPipelineLayout *layout, + const char *shader_name, + VkRenderPass render_pass) +{ + return gsk_vulkan_pipeline_new (GSK_TYPE_VULKAN_BLUR_PIPELINE, layout, shader_name, render_pass); +} + +gsize +gsk_vulkan_blur_pipeline_count_vertex_data (GskVulkanBlurPipeline *pipeline) +{ + return sizeof (GskVulkanBlurInstance); +} + +void +gsk_vulkan_blur_pipeline_collect_vertex_data (GskVulkanBlurPipeline *pipeline, + guchar *data, + const graphene_rect_t *rect, + double blur_radius) +{ + GskVulkanBlurInstance *instance = (GskVulkanBlurInstance *) data; + + instance->rect[0] = rect->origin.x; + instance->rect[1] = rect->origin.y; + instance->rect[2] = rect->size.width; + instance->rect[3] = rect->size.height; + instance->tex_rect[0] = 0.0; + instance->tex_rect[1] = 0.0; + instance->tex_rect[2] = 1.0; + instance->tex_rect[3] = 1.0; + instance->blur_radius = blur_radius; +} + +gsize +gsk_vulkan_blur_pipeline_draw (GskVulkanBlurPipeline *pipeline, + VkCommandBuffer command_buffer, + gsize offset, + gsize n_commands) +{ + vkCmdDraw (command_buffer, + 6, n_commands, + 0, offset); + + return n_commands; +} diff --git a/gsk/gskvulkanblurpipelineprivate.h b/gsk/gskvulkanblurpipelineprivate.h new file mode 100644 index 0000000000..44b139d4bf --- /dev/null +++ b/gsk/gskvulkanblurpipelineprivate.h @@ -0,0 +1,32 @@ +#ifndef __GSK_VULKAN_BLUR_PIPELINE_PRIVATE_H__ +#define __GSK_VULKAN_BLUR_PIPELINE_PRIVATE_H__ + +#include + +#include "gskvulkanpipelineprivate.h" + +G_BEGIN_DECLS + +typedef struct _GskVulkanBlurPipelineLayout GskVulkanBlurPipelineLayout; + +#define GSK_TYPE_VULKAN_BLUR_PIPELINE (gsk_vulkan_blur_pipeline_get_type ()) + +G_DECLARE_FINAL_TYPE (GskVulkanBlurPipeline, gsk_vulkan_blur_pipeline, GSK, VULKAN_BLUR_PIPELINE, GskVulkanPipeline) + +GskVulkanPipeline * gsk_vulkan_blur_pipeline_new (GskVulkanPipelineLayout *layout, + const char *shader_name, + VkRenderPass render_pass); + +gsize gsk_vulkan_blur_pipeline_count_vertex_data (GskVulkanBlurPipeline *pipeline); +void gsk_vulkan_blur_pipeline_collect_vertex_data (GskVulkanBlurPipeline *pipeline, + guchar *data, + const graphene_rect_t *rect, + double radius); +gsize gsk_vulkan_blur_pipeline_draw (GskVulkanBlurPipeline *pipeline, + VkCommandBuffer command_buffer, + gsize offset, + gsize n_commands); + +G_END_DECLS + +#endif /* __GSK_VULKAN_BLUR_PIPELINE_PRIVATE_H__ */ diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c index cf98e184e0..4da8e48566 100644 --- a/gsk/gskvulkanrender.c +++ b/gsk/gskvulkanrender.c @@ -11,6 +11,7 @@ #include "gskvulkanrenderpassprivate.h" #include "gskvulkanblendpipelineprivate.h" +#include "gskvulkanblurpipelineprivate.h" #include "gskvulkanborderpipelineprivate.h" #include "gskvulkanboxshadowpipelineprivate.h" #include "gskvulkancolorpipelineprivate.h" @@ -340,6 +341,9 @@ gsk_vulkan_render_get_pipeline (GskVulkanRender *self, { "outset-shadow", gsk_vulkan_box_shadow_pipeline_new }, { "outset-shadow-clip", gsk_vulkan_box_shadow_pipeline_new }, { "outset-shadow-clip-rounded", gsk_vulkan_box_shadow_pipeline_new }, + { "blur", gsk_vulkan_blur_pipeline_new }, + { "blur-clip", gsk_vulkan_blur_pipeline_new }, + { "blur-clip-rounded", gsk_vulkan_blur_pipeline_new }, }; g_return_val_if_fail (type < GSK_VULKAN_N_PIPELINES, NULL); diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c index b5bab5f39e..f3b2b0cb92 100644 --- a/gsk/gskvulkanrenderpass.c +++ b/gsk/gskvulkanrenderpass.c @@ -7,6 +7,7 @@ #include "gskrenderer.h" #include "gskroundedrectprivate.h" #include "gskvulkanblendpipelineprivate.h" +#include "gskvulkanblurpipelineprivate.h" #include "gskvulkanborderpipelineprivate.h" #include "gskvulkanboxshadowpipelineprivate.h" #include "gskvulkanclipprivate.h" @@ -31,6 +32,7 @@ typedef enum { GSK_VULKAN_OP_COLOR, GSK_VULKAN_OP_LINEAR_GRADIENT, GSK_VULKAN_OP_OPACITY, + GSK_VULKAN_OP_BLUR, GSK_VULKAN_OP_COLOR_MATRIX, GSK_VULKAN_OP_BORDER, GSK_VULKAN_OP_INSET_SHADOW, @@ -231,6 +233,20 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, g_array_append_val (self->render_ops, op); return; + case GSK_BLUR_NODE: + if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds)) + pipeline_type = GSK_VULKAN_PIPELINE_BLUR; + else if (constants->clip.type == GSK_VULKAN_CLIP_RECT) + pipeline_type = GSK_VULKAN_PIPELINE_BLUR_CLIP; + else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR) + pipeline_type = GSK_VULKAN_PIPELINE_BLUR_CLIP_ROUNDED; + else + FALLBACK ("Blur nodes can't deal with clip type %u\n", constants->clip.type); + op.type = GSK_VULKAN_OP_BLUR; + op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type); + g_array_append_val (self->render_ops, op); + return; + case GSK_COLOR_MATRIX_NODE: if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds)) pipeline_type = GSK_VULKAN_PIPELINE_COLOR_MATRIX; @@ -543,6 +559,18 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self, } break; + case GSK_VULKAN_OP_BLUR: + { + GskRenderNode *child = gsk_blur_node_get_child (op->render.node); + + op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self, + render, + uploader, + child, + &child->bounds); + } + break; + case GSK_VULKAN_OP_COLOR_MATRIX: { GskRenderNode *child = gsk_color_matrix_node_get_child (op->render.node); @@ -607,6 +635,11 @@ gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self) n_bytes += op->render.vertex_count; break; + case GSK_VULKAN_OP_BLUR: + op->render.vertex_count = gsk_vulkan_blur_pipeline_count_vertex_data (GSK_VULKAN_BLUR_PIPELINE (op->render.pipeline)); + n_bytes += op->render.vertex_count; + break; + case GSK_VULKAN_OP_BORDER: op->render.vertex_count = gsk_vulkan_border_pipeline_count_vertex_data (GSK_VULKAN_BORDER_PIPELINE (op->render.pipeline)); n_bytes += op->render.vertex_count; @@ -707,6 +740,17 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self, } break; + case GSK_VULKAN_OP_BLUR: + { + op->render.vertex_offset = offset + n_bytes; + gsk_vulkan_blur_pipeline_collect_vertex_data (GSK_VULKAN_BLUR_PIPELINE (op->render.pipeline), + data + n_bytes + offset, + &op->render.node->bounds, + gsk_blur_node_get_radius (op->render.node)); + n_bytes += op->render.vertex_count; + } + break; + case GSK_VULKAN_OP_COLOR_MATRIX: { op->render.vertex_offset = offset + n_bytes; @@ -792,6 +836,7 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self, case GSK_VULKAN_OP_SURFACE: case GSK_VULKAN_OP_TEXTURE: case GSK_VULKAN_OP_OPACITY: + case GSK_VULKAN_OP_BLUR: case GSK_VULKAN_OP_COLOR_MATRIX: op->render.descriptor_set_index = gsk_vulkan_render_reserve_descriptor_set (render, op->render.source); break; @@ -899,6 +944,39 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, current_draw_index, 1); break; + case GSK_VULKAN_OP_BLUR: + if (current_pipeline != op->render.pipeline) + { + current_pipeline = op->render.pipeline; + vkCmdBindPipeline (command_buffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, + gsk_vulkan_pipeline_get_pipeline (current_pipeline)); + vkCmdBindVertexBuffers (command_buffer, + 0, + 1, + (VkBuffer[1]) { + gsk_vulkan_buffer_get_buffer (vertex_buffer) + }, + (VkDeviceSize[1]) { op->render.vertex_offset }); + current_draw_index = 0; + } + + vkCmdBindDescriptorSets (command_buffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, + gsk_vulkan_pipeline_layout_get_pipeline_layout (layout), + 0, + 1, + (VkDescriptorSet[1]) { + gsk_vulkan_render_get_descriptor_set (render, op->render.descriptor_set_index) + }, + 0, + NULL); + + current_draw_index += gsk_vulkan_blur_pipeline_draw (GSK_VULKAN_BLUR_PIPELINE (current_pipeline), + command_buffer, + current_draw_index, 1); + break; + case GSK_VULKAN_OP_COLOR: if (current_pipeline != op->render.pipeline) { diff --git a/gsk/gskvulkanrenderprivate.h b/gsk/gskvulkanrenderprivate.h index 29860f086e..4c01e82e9a 100644 --- a/gsk/gskvulkanrenderprivate.h +++ b/gsk/gskvulkanrenderprivate.h @@ -31,6 +31,9 @@ typedef enum { GSK_VULKAN_PIPELINE_OUTSET_SHADOW, GSK_VULKAN_PIPELINE_OUTSET_SHADOW_CLIP, GSK_VULKAN_PIPELINE_OUTSET_SHADOW_CLIP_ROUNDED, + GSK_VULKAN_PIPELINE_BLUR, + GSK_VULKAN_PIPELINE_BLUR_CLIP, + GSK_VULKAN_PIPELINE_BLUR_CLIP_ROUNDED, /* add more */ GSK_VULKAN_N_PIPELINES } GskVulkanPipelineType; diff --git a/gsk/meson.build b/gsk/meson.build index 83be577f1f..7725171ae9 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -50,6 +50,7 @@ gsk_private_vulkan_compiled_shaders = [] if have_vulkan gsk_private_sources += files([ 'gskvulkanblendpipeline.c', + 'gskvulkanblurpipeline.c', 'gskvulkanborderpipeline.c', 'gskvulkanboxshadowpipeline.c', 'gskvulkanbuffer.c', diff --git a/gsk/resources/vulkan/blur-clip-rounded.frag.spv b/gsk/resources/vulkan/blur-clip-rounded.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..bdec4c9e9b2d8c4dfaba4f7619fba110b904af6c GIT binary patch literal 10812 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 literal 0 HcmV?d00001 diff --git a/gsk/resources/vulkan/blur-clip-rounded.vert.spv b/gsk/resources/vulkan/blur-clip-rounded.vert.spv new file mode 100644 index 0000000000000000000000000000000000000000..2e3c5ff52222157342ec8ee98fbbe69339599f7a GIT binary patch literal 5172 zcmZ9OiyFw(&oWdK9-HXY`iVYUtDOmog4Y6hq% zUA$i+uc&y7ZeH>(VrfOz-&0S|Q%}F&KKqLm%jac%@4Mdht#4iS8M`Je=*hC<`0s@5 z?^&nK$|k|HY+5$C===IN^)G3)YfF}$zf{MGSyy4yGXrMp2HUE6!+0Fr3GM}tg2%x@ za0na$pMx&`n?!$rB;DE6tgnBtZ~gkd{>ul4#>NI)?b}A{gQIz)K3L1g>qG5)dtKl0 zi7#&qjZV~3Lj^}#Mqt&i9aAm07g-)1l z+dc;G_&i6~8{E>IXw+K&(>h8p@9Ytj{btGqg1 z-B$Aa7(ND1_vF3hjg7@F-J>-ho!^z+DsQ^q$;JI{9Ua_UA8*%pT-m7AcXalB4<7V^ z`gmsuTI@&N=2)|pxASI$JYB^bQFlGxN^_#kc!&FL;G6Q>>&5s!II9&US5SOYdE=V; zj!wxamEw&t2XRfaIbJI?-yGV;YAv5|Px^d=>@}opZE`mi#@6ET4s8oM-T!HPG{rj! zpLeKlH3-f7QyWM$?@sM|ppX5#hQ2=5_x$Gpo7`{6cex0dGtN-W=6to7@A(~_-&K5f zex2s>EFH5>xo4O1LnZIz>MFj|nCtoJwRY!vc5=NZ@vr@SMjbakg=jK;FPMwpvyyj% zUj99vUQNtrUsK9hUChVh+K$W3F`M2T=06#J5`8bQom=ub#ClGHpG@x@HP<|a-ZAx+ zCHEUvbH4qlz_ys0ocjf!Cc^VY;w;;>Dm-6;sp$#rw34fbb~>@VqfII5@C;qU9L^EO zdgrjyb@cANpWfKLFXmJ{mkl6lJKA>_zh{nn*7Mla7Wyhs3wRzwaL?Uw&qH1-HP4ry z+v0qWqj&G}VIX(@E%b43@*k9Au3YS2i5>G?_5ZLOGp~NR?>+oGiMOD$@>4{p=Hm)=^dC4Y$C`H}CDlDn4q*%qThv**$zF}*zR=K{Y<1u3EaLl(Ucg%cG0PisF;pe5M9%t)3->_pb?-#`BojeIw z6E^n~-lvGuHJ*m637g)#*^77a3^13TnExzsI{!Jinur?rmh<~PvEKd4{$XRdo*ty{zq^p@Y~-> z|0$RY)b-4!{|uoo@^6E5vI0;yYeMY)*4HM~`P~jgG~6 zoJ;Jv#d$0yRueXJhW9+;)Vl<(CTywqtMJsj6s{(YJ&&)UnM+UX>FdPSVhimX#A@kz zEQ34W7QXX|)zb600B%lmI7g4?VU3Q(9xo(L?{NiOP1w>sUIb6~xDu`=Y^Nr}0`#0tm`tO4p d7zW`VEp`3olCR(|hihyD(}8&$vu-u({x4w&v(Nwl literal 0 HcmV?d00001 diff --git a/gsk/resources/vulkan/blur-clip.frag.spv b/gsk/resources/vulkan/blur-clip.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..d6619c9246626a4e121a71d8b38ccd4c6466aa43 GIT binary patch literal 4068 zcmZ9NiEsfN$heSZbA)-`CR@J83vM=l}12&$-L#o|XsJbwtrD{yiA|5;dR2(F5QpnisVv zJ~woHsHavR?b*I#vx)^#OCnUWFq#{+;!3|hVr?iM{`35^CQ)2zE;0fD&|XZxtJe~CyOKXc&eywc19PMM@o&+te_1=b`5Q; zeE~H_N^y1l)Y#VEsj=<7;5KT{$5$&g;#PKzrc$a*CS&c^dHvXyUj8S# zCGfTQ+(aSKwM0wt7n8U>T8TefYE0&<@x@{(sg~5~gl|k)vo+d4T(8s%rDRS^vl&rj^`MckHd-EqutYWmzuhkXdi*Vy&b}j0owTI9mM5hh0(ZC zBZO&N zbWd%`I^*(*;>CJnl5Hh&)c&Je<2>NkIQ!?^L-l< ze!Li;8&6Uv`??2Tr6w-QaW~$lJ(;7f@fyrpV(&_9F0qHd7V`rC$JDrokXOxOusP(lZZs?K z=5XFdu;bkrPk+E0o0xaDBhfwymYZ(Pxlbk9tNX0KnRpiF8hTUgy~`~JZ^d_EKGqU% zOHgzD+lke>rZB!I<(%I~+?8VM?IpIByn1~<<`Zy^cpq=gJVma%HlaC8Nr{bDbg!^hfx!ubBEwO{UF z;cmr#g95e({RWBq(Cfd!T<2c0Iaj=gjIQTfY$YZi^xqS^Pxa;&8=F`C9`@$kA2Gix zY8+GJdCC97sqDtwk6Lv;^RQj$T(`f6#;)1lL-%QqxDMw$l=A<=8;5-M$ui8xcgq~U zS4%SSQeyKh$D7YN4`cEHuSxMu*68>nm>T&j>6|WN`7mcKv30_nb;RA6e9$~foYg!A zRwsWet@Su@7v|V}s$2gF%wAfJIqtsY!oEEd@5*Nd7S6Gg*uAd8+asRE2F$w`d%phe z2kdyy47@vo_Y&{RVD*P);Ncng*bICkgUxq3gUvTG1D~6L;~DsTitRD?<~PvTefeG7 z&$({L@4)=lZNtKS>`eJ^_PfA-FXheQS;&PPPZOJC4;FIt63d4i&k&nK-W;BvoUv!u zkNw4+?8kdI`aigf0sH~X$MJ)B$Mx3g!#{_a<2Uv+h<`ria`?Z|h@ZvGp13nr^Ycg_Jw??{}QqFuT#&x zoWkTzVqr}$r+ldY3fS`t@6@ZrYUHh9FUc9(NBx**_Zr^)>pj~y@OjL~@iTbG^@p6xg|oUJ`Bb|3b)`f#>y5_`64 z98)ubmk;$z#MTdIJ3%a$J=-!^KAdfZ*!~V@TP0Q_Zw=ooxuAcG*t!8v5_`vCevMd- ze9+X1H(=M&9%~TGskMerAnI_73K{LjHG&?SWzPtA7tuBX3Q) zE0}p4I|Vlfe-*QqVgjg=*b4OO6;1&-oa;>_cqMwy1&~gCm+mjp<|z8&R64ame}8{{{Y}jYb^i( literal 0 HcmV?d00001 diff --git a/gsk/resources/vulkan/blur-clip.vert.spv b/gsk/resources/vulkan/blur-clip.vert.spv new file mode 100644 index 0000000000000000000000000000000000000000..2e3c5ff52222157342ec8ee98fbbe69339599f7a GIT binary patch literal 5172 zcmZ9OiyFw(&oWdK9-HXY`iVYUtDOmog4Y6hq% zUA$i+uc&y7ZeH>(VrfOz-&0S|Q%}F&KKqLm%jac%@4Mdht#4iS8M`Je=*hC<`0s@5 z?^&nK$|k|HY+5$C===IN^)G3)YfF}$zf{MGSyy4yGXrMp2HUE6!+0Fr3GM}tg2%x@ za0na$pMx&`n?!$rB;DE6tgnBtZ~gkd{>ul4#>NI)?b}A{gQIz)K3L1g>qG5)dtKl0 zi7#&qjZV~3Lj^}#Mqt&i9aAm07g-)1l z+dc;G_&i6~8{E>IXw+K&(>h8p@9Ytj{btGqg1 z-B$Aa7(ND1_vF3hjg7@F-J>-ho!^z+DsQ^q$;JI{9Ua_UA8*%pT-m7AcXalB4<7V^ z`gmsuTI@&N=2)|pxASI$JYB^bQFlGxN^_#kc!&FL;G6Q>>&5s!II9&US5SOYdE=V; zj!wxamEw&t2XRfaIbJI?-yGV;YAv5|Px^d=>@}opZE`mi#@6ET4s8oM-T!HPG{rj! zpLeKlH3-f7QyWM$?@sM|ppX5#hQ2=5_x$Gpo7`{6cex0dGtN-W=6to7@A(~_-&K5f zex2s>EFH5>xo4O1LnZIz>MFj|nCtoJwRY!vc5=NZ@vr@SMjbakg=jK;FPMwpvyyj% zUj99vUQNtrUsK9hUChVh+K$W3F`M2T=06#J5`8bQom=ub#ClGHpG@x@HP<|a-ZAx+ zCHEUvbH4qlz_ys0ocjf!Cc^VY;w;;>Dm-6;sp$#rw34fbb~>@VqfII5@C;qU9L^EO zdgrjyb@cANpWfKLFXmJ{mkl6lJKA>_zh{nn*7Mla7Wyhs3wRzwaL?Uw&qH1-HP4ry z+v0qWqj&G}VIX(@E%b43@*k9Au3YS2i5>G?_5ZLOGp~NR?>+oGiMOD$@>4{p=Hm)=^dC4Y$C`H}CDlDn4q*%qThv**$zF}*zR=K{Y<1u3EaLl(Ucg%cG0PisF;pe5M9%t)3->_pb?-#`BojeIw z6E^n~-lvGuHJ*m637g)#*^77a3^13TnExzsI{!Jinur?rmh<~PvEKd4{$XRdo*ty{zq^p@Y~-> z|0$RY)b-4!{|uoo@^6E5vI0;yYeMY)*4HM~`P~jgG~6 zoJ;Jv#d$0yRueXJhW9+;)Vl<(CTywqtMJsj6s{(YJ&&)UnM+UX>FdPSVhimX#A@kz zEQ34W7QXX|)zb600B%lmI7g4?VU3Q(9xo(L?{NiOP1w>sUIb6~xDu`=Y^Nr}0`#0tm`tO4p d7zW`VEp`3olCR(|hihyD(}8&$vu-u({x4w&v(Nwl literal 0 HcmV?d00001 diff --git a/gsk/resources/vulkan/blur.frag b/gsk/resources/vulkan/blur.frag new file mode 100644 index 0000000000..2dd584b0c6 --- /dev/null +++ b/gsk/resources/vulkan/blur.frag @@ -0,0 +1,50 @@ +#version 420 core + +#include "clip.frag.glsl" + +layout(location = 0) in vec2 inPos; +layout(location = 1) in flat vec2 inSize; +layout(location = 2) in vec2 inTexCoord; +layout(location = 3) in float inRadius; + +layout(set = 0, binding = 0) uniform sampler2D inTexture; + +layout(location = 0) out vec4 color; + +const int samples_x = 15; // must be odd +const int samples_y = 15; // must be odd + +const int half_samples_x = samples_x / 2; +const int half_samples_y = samples_y / 2; + +float Gaussian (float sigma, float x) +{ + return exp ( - (x * x) / (2.0 * sigma * sigma)); +} + +vec4 blur_pixel (in vec2 uv) +{ + float total = 0.0; + vec4 ret = vec4 (0); + float pixel_size_x = (1.0 / inSize.x); + float pixel_size_y = (1.0 / inSize.y); + + for (int y = 0; y < samples_y; ++y) + { + float fy = Gaussian (inRadius, float(y) - float(half_samples_x)); + float offset_y = float(y - half_samples_y) * pixel_size_y; + for (int x = 0; x < samples_x; ++x) + { + float fx = Gaussian (inRadius, float(x) - float(half_samples_x)); + float offset_x = float(x - half_samples_x) * pixel_size_x; + total += fx * fy; + ret += texture(inTexture, uv + vec2(offset_x, offset_y)) * fx * fy; + } + } + return ret / total; +} + +void main() +{ + color = clip (inPos, blur_pixel (inTexCoord)); +} diff --git a/gsk/resources/vulkan/blur.frag.glsl b/gsk/resources/vulkan/blur.frag.glsl new file mode 100644 index 0000000000..528db202b0 --- /dev/null +++ b/gsk/resources/vulkan/blur.frag.glsl @@ -0,0 +1,13 @@ +#version 420 core + +#include "clip.frag.glsl" + +layout(location = 0) in vec2 inPos; +layout(location = 1) in float inRadius; + +layout(location = 0) out vec4 color; + +void main() +{ + color = clip (inPos, vec4(1, 0, 0, 0)); +} diff --git a/gsk/resources/vulkan/blur.frag.spv b/gsk/resources/vulkan/blur.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..d6619c9246626a4e121a71d8b38ccd4c6466aa43 GIT binary patch literal 4068 zcmZ9NiEsfN$heSZbA)-`CR@J83vM=l}12&$-L#o|XsJbwtrD{yiA|5;dR2(F5QpnisVv zJ~woHsHavR?b*I#vx)^#OCnUWFq#{+;!3|hVr?iM{`35^CQ)2zE;0fD&|XZxtJe~CyOKXc&eywc19PMM@o&+te_1=b`5Q; zeE~H_N^y1l)Y#VEsj=<7;5KT{$5$&g;#PKzrc$a*CS&c^dHvXyUj8S# zCGfTQ+(aSKwM0wt7n8U>T8TefYE0&<@x@{(sg~5~gl|k)vo+d4T(8s%rDRS^vl&rj^`MckHd-EqutYWmzuhkXdi*Vy&b}j0owTI9mM5hh0(ZC zBZO&N zbWd%`I^*(*;>CJnl5Hh&)c&Je<2>NkIQ!?^L-l< ze!Li;8&6Uv`??2Tr6w-QaW~$lJ(;7f@fyrpV(&_9F0qHd7V`rC$JDrokXOxOusP(lZZs?K z=5XFdu;bkrPk+E0o0xaDBhfwymYZ(Pxlbk9tNX0KnRpiF8hTUgy~`~JZ^d_EKGqU% zOHgzD+lke>rZB!I<(%I~+?8VM?IpIByn1~<<`Zy^cpq=gJVma%HlaC8Nr{bDbg!^hfx!ubBEwO{UF z;cmr#g95e({RWBq(Cfd!T<2c0Iaj=gjIQTfY$YZi^xqS^Pxa;&8=F`C9`@$kA2Gix zY8+GJdCC97sqDtwk6Lv;^RQj$T(`f6#;)1lL-%QqxDMw$l=A<=8;5-M$ui8xcgq~U zS4%SSQeyKh$D7YN4`cEHuSxMu*68>nm>T&j>6|WN`7mcKv30_nb;RA6e9$~foYg!A zRwsWet@Su@7v|V}s$2gF%wAfJIqtsY!oEEd@5*Nd7S6Gg*uAd8+asRE2F$w`d%phe z2kdyy47@vo_Y&{RVD*P);Ncng*bICkgUxq3gUvTG1D~6L;~DsTitRD?<~PvTefeG7 z&$({L@4)=lZNtKS>`eJ^_PfA-FXheQS;&PPPZOJC4;FIt63d4i&k&nK-W;BvoUv!u zkNw4+?8kdI`aigf0sH~X$MJ)B$Mx3g!#{_a<2Uv+h<`ria`?Z|h@ZvGp13nr^Ycg_Jw??{}QqFuT#&x zoWkTzVqr}$r+ldY3fS`t@6@ZrYUHh9FUc9(NBx**_Zr^)>pj~y@OjL~@iTbG^@p6xg|oUJ`Bb|3b)`f#>y5_`64 z98)ubmk;$z#MTdIJ3%a$J=-!^KAdfZ*!~V@TP0Q_Zw=ooxuAcG*t!8v5_`vCevMd- ze9+X1H(=M&9%~TGskMerAnI_73K{LjHG&?SWzPtA7tuBX3Q) zE0}p4I|Vlfe-*QqVgjg=*b4OO6;1&-oa;>_cqMwy1&~gCm+mjp<|z8&R64ame}8{{{Y}jYb^i( literal 0 HcmV?d00001 diff --git a/gsk/resources/vulkan/blur.vert b/gsk/resources/vulkan/blur.vert new file mode 100644 index 0000000000..4a5a138af8 --- /dev/null +++ b/gsk/resources/vulkan/blur.vert @@ -0,0 +1,41 @@ + +#version 420 core + +#include "clip.vert.glsl" + +layout(location = 0) in vec4 inRect; +layout(location = 1) in vec4 inTexRect; +layout(location = 2) in float inRadius; + +layout(location = 0) out vec2 outPos; +layout(location = 1) out flat vec2 outSize; +layout(location = 2) out vec2 outTexCoord; +layout(location = 3) out flat float outRadius; + +out gl_PerVertex { + vec4 gl_Position; +}; + +vec2 offsets[6] = { vec2(0.0, 0.0), + vec2(1.0, 0.0), + vec2(0.0, 1.0), + vec2(0.0, 1.0), + vec2(1.0, 0.0), + vec2(1.0, 1.0) }; + +void main() { + vec4 rect = clip (inRect); + vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex]; + gl_Position = push.mvp * vec4 (pos, 0.0, 1.0); + + outPos = pos; + outSize = inRect.zw; + + vec4 texrect = vec4((rect.xy - inRect.xy) / inRect.zw, + rect.zw / inRect.zw); + texrect = vec4(inTexRect.xy + inTexRect.zw * texrect.xy, + inTexRect.zw * texrect.zw); + outTexCoord = texrect.xy + texrect.zw * offsets[gl_VertexIndex]; + + outRadius = inRadius; +} diff --git a/gsk/resources/vulkan/blur.vert.glsl b/gsk/resources/vulkan/blur.vert.glsl new file mode 100644 index 0000000000..f50ca37980 --- /dev/null +++ b/gsk/resources/vulkan/blur.vert.glsl @@ -0,0 +1,30 @@ +#version 420 core + +#include "clip.vert.glsl" + +layout(location = 0) in vec4 inRect; +layout(location = 1) in float inRadius; + +layout(location = 0) out vec2 outPos; +layout(location = 1) out flat float outRadius; + +out gl_PerVertex { + vec4 gl_Position; +}; + +vec2 offsets[6] = { vec2(0.0, 0.0), + vec2(1.0, 0.0), + vec2(0.0, 1.0), + vec2(0.0, 1.0), + vec2(1.0, 0.0), + vec2(1.0, 1.0) }; + +void main() { + vec4 rect = clip (inRect); + + vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex]; + gl_Position = push.mvp * vec4 (pos, 0.0, 1.0); + outPos = pos; + outRadius = inRadius; +} + diff --git a/gsk/resources/vulkan/blur.vert.spv b/gsk/resources/vulkan/blur.vert.spv new file mode 100644 index 0000000000000000000000000000000000000000..f83b77a2e76963d3836be1f5864e0791407def02 GIT binary patch literal 3440 zcmZ9NX>(Ln5QZ-#6Cj8P$f6}U5mXS2sH`HJhyxl;NDx;XLgps9n#_!uNeCb=Wm)A{ z|ARl$FIqm&ncHxSLp7)0x0lnW``pRU#)F%(Yy1$>VxFn++vLeYS&K!^rY%(N=#MIf|S>t|ATOHqu2NB9D+E{%vIcnmx^}YY!xf{T)$Y$_1j$WE825QtF5X-4UcLawXDV+vTSat z=pJ61KXDFSpHX&`vL(Eey)!@G%lo~A_djL#K1F*vMHpWPcV|~-m)UFF`1!z z!cy~AzS7UvueV$Ix;`V>JNUp)Coc7LT>}mF?)!yQjPP^Bi zZBwPO!->~td99mr>E}$mZ}V5?<5nym=_C+DK%#fXJ_HN zoXM83bL_14sd0dvDR`!MkSF`cU~Zh+YTuoA(Y~3l584J(OY zRjhh1{d^zvJ1E}IaC%b*;9X+hm$Q8Xxkilrb;-FJ%tg+7U#s-0mT>KH?+$`p=CFS* zK8Wl&BshDj-=zv?Ub(3XXD{XMAf9hN{jAsiJ*j^P&hKboQ`hD>`r5lH_PY@eat)<# zC}QoOHqSQJ-i7ZjB8(Zss$G2#+6a3c*^9q-75m-P`F}IJoH7R9QtI;hZ)4ZrT)V;6 zQAb=yOS~OjpO?V)(HJ@N?_k#^f3C!Se{#mV??PP1n2E8^BXUak>_*SBUoVEw9*~?q z!R;-vd~o~F#RG0js^bN)XPCnnMO|NOj#=0fYZm*Pu%Wa&b8XgYPmU!1iQPAypj|ASJu58B1P?XdrZ zZfw}azIC}%yc6G}cXk=`4~*ZsxqQ3(5o-@zui%5|hbmZqf6w&4KsMi}Z{$3=*HB(A@YCVBR-CpQ~tM-dmG)Fv{}D>ku$Gv!oQ)u6W^S9eIM^5@^Q|2 zbmMLi(F+UU98P~*AQnIbGTk|^3hx48enY^_X&D+CKF&e#Z{f(r{L-tpMm8Rm%hK3 zeV;@(mp*aU6nZuO23Sss8viWgr{T<@PsGolS8KfqmQx}=d_RY)o^=Z>r-W~u^#z={ z^oetjIfuE~mK68{bh2-CX*_ca)=Bi?+x)k6t~00W7CHef}a` z_51=Xr-W~u|2>?!^ogGSfNl-0;Fi$ktUb78bmLvYwbAADi+Oa=&1nu}^oeJ2Z4XQQFIAsG{5#`s$5zC(1v!o1X7*9Uzd6sa$NgR``TyY6&GA15 C#`?kl literal 0 HcmV?d00001 diff --git a/gsk/resources/vulkan/meson.build b/gsk/resources/vulkan/meson.build index 8595ccf605..bdca123ed6 100644 --- a/gsk/resources/vulkan/meson.build +++ b/gsk/resources/vulkan/meson.build @@ -8,6 +8,7 @@ gsk_private_vulkan_fragment_shaders = [ 'blend.frag', + 'blur.frag', 'border.frag', 'color.frag', 'color-matrix.frag', @@ -18,6 +19,7 @@ gsk_private_vulkan_fragment_shaders = [ gsk_private_vulkan_vertex_shaders = [ 'blend.vert', + 'blur.vert', 'border.vert', 'color.vert', 'color-matrix.vert', -- 2.30.2